%------------------------------------------------------------
% Author: vjache
% Created: 01.11.2009
% Description: 	This module is a reference implementation of a 
%				'map' behavior based on 'ets' module.
%------------------------------------------------------------
-module(map_ets).

-include("../include/map.hrl").
-include("../include/iter.hrl").
%------------------------------------------------------------
% Exported Functions
%------------------------------------------------------------
-export([new/1,new_concurrent_write/1]).
-export([
		 close/1,
		 clear/1,
		 contains/2,
		 entries_by_key/2,
		 entries_by_keys/2,
		 get/2,
		 keys/1,
		 m_iter/2,
		 m_pipe/1,
		 open/1,
		 put/3,
		 put_entries/2,
		 remove_entries/2,
		 remove_entry/3,
		 remove_key/2,
		 remove_keys/2,
		 size/1,
		 values_by_key/2,
		 values_by_keys/2
		]).
%------------------------------------------------------------
% API Functions
%------------------------------------------------------------

%%-----------------------------------------------------------
%% new(Type)->map()
%% Description: Creates a public ets based map of specified 
%%				type. Type= set|bag|ordered_bag|duplicated_bag.
%%-----------------------------------------------------------
new(Type) 
  when	Type==set orelse 
		Type==ordered_set orelse 
		Type==bag orelse 
		Type==duplicated_bag ->
	#map{impl=?MODULE,param=[public, Type]}.
%%-----------------------------------------------------------
%% new_concurrent_write(Type)->map()
%% Description: Creates a public ets based map of specified 
%%				type with concurrent write support. 
%%				Type= set|bag|ordered_bag|duplicated_bag.
%%-----------------------------------------------------------
new_concurrent_write(Type) 
  when	Type==set orelse 
		Type==ordered_set orelse 
		Type==bag orelse 
		Type==duplicated_bag ->
	#map{impl=?MODULE,param=[public,{write_concurrency,true}, Type]}.


open(EtsOptions) ->
	ets:new(?MODULE, EtsOptions).
close(Handle)->
	ets:delete(Handle).
put(Handle,Key,Value)->
	ets:insert(Handle, {Key,Value}).
get(Handle,Key)->
	case values_by_key(Handle,Key) of
		[] ->
			undefined;
		[V|_] ->
			{ok,V}
	end.
remove_key(Handle,Key)->
	ets:delete(Handle, Key).
remove_entry(Handle,Key,Value)->
	ets:delete_object(Handle,{Key,Value}).
entries_by_key(Handle,Key)->
	ets:lookup(Handle, Key).
values_by_key(Handle,Key)->
	[V||{_K,V}<-entries_by_key(Handle,Key)].
size(Handle)->
	ets:info(Handle,size).
contains(Handle,Key)->
	case (catch ets:lookup_element(Handle, Key, 1)) of
		badarg ->
			false;
		Key ->
			true
	end.
clear(Handle)->
	ets:delete_all_objects(Handle).
%------------------------------------------------------------
% Bulk API
%------------------------------------------------------------
put_entries(Handle,EntryIter) when ?IS_ITER(EntryIter) ->
	{S,ok}=iter:foreach(
	  EntryIter,
	  fun({K,V})->
			  put(Handle, K, V)
	  end),
	iter:close(S).
values_by_keys(Handle,KeyIter) when ?IS_ITER(KeyIter) ->
	iter_concat:new(
	  iter_mapper:new(
		KeyIter, 
		fun(Key)->
				iter:from_list(values_by_key(Handle,Key))
		end)).
entries_by_keys(Handle,KeyIter) when ?IS_ITER(KeyIter) ->
	iter_concat:new(
	  iter_mapper:new(
		KeyIter, 
		fun(Key)->
				iter:from_list(entries_by_key(Handle,Key))
		end)).
remove_entries(Handle,EntryIter) when ?IS_ITER(EntryIter) ->
	{S,ok}=iter:foreach(
	  EntryIter,
	  fun({K,V})->
			  remove_entry(Handle, K, V)
	  end),
	iter:close(S).
remove_keys(Handle,KeyIter) when ?IS_ITER(KeyIter) ->
	{S,ok}=iter:foreach(
	  KeyIter,
	  fun(K)->
			  remove_key(Handle, K)
	  end),
	iter:close(S).
keys(Handle)->
	iter_ets_keys:new(Handle).

m_pipe(Handle)->
	pipe_modifier:new(Handle).
m_iter(Handle,ModifIter) when ?IS_ITER(ModifIter) ->
	Pump=pump:new(ModifIter, m_pipe(Handle)),
	pump:init(Pump).
%------------------------------------------------------------
% Local Functions
%------------------------------------------------------------

